package com.example.swimmingpool.aop;

import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.json.JSONUtil;
import com.example.swimmingpool.annotation.RecordLog;
import com.example.swimmingpool.entity.log.Log;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;


@Component
@Aspect
@Slf4j
public class RecordLogAspect {

    private static final ThreadLocal<LocalDateTime> threadLocal = new ThreadLocal<>();

    private final ExecutorService executor = ExecutorBuilder.create()
            .setCorePoolSize(5)
            .setMaxPoolSize(10)
            .setWorkQueue(new LinkedBlockingQueue<>(100))
            .build();

    @Resource
    private MongoTemplate mongoTemplate;

    @Pointcut("@annotation(com.example.swimmingpool.annotation.RecordLog)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object log(ProceedingJoinPoint pjp) throws Throwable {
        threadLocal.set(LocalDateTime.now());
        Object result = pjp.proceed();
        setLog(pjp);
        return result;

    }

    public void setLog(ProceedingJoinPoint pjp) {
        var createTime = threadLocal.get();
        log.info(String.valueOf(createTime));
        threadLocal.remove();
        var startTime = createTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        var signature = (MethodSignature) pjp.getSignature();
        var method = signature.getMethod();
        var recordlog = method.getAnnotation(RecordLog.class);
        var endTime = System.currentTimeMillis();
        log.info("方法执行了{}s", (endTime - startTime) * 1.0 / 1000);
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            // 取得请求对象
            HttpServletRequest request = requestAttributes.getRequest();

            // 方法名称
            String className = pjp.getTarget().getClass().getName();
            String methodName = pjp.getSignature().getName();

            // 获取请求参数
            String queryString = request.getQueryString();
            Object[] args = pjp.getArgs();
            String params = "";
            if (args.length > 0) {
                if ("POST".equals(request.getMethod())) {
                    params = JSONUtil.toJsonStr(args);

                } else if ("GET".equals(request.getMethod())) {
                    params = queryString;
                }
            }
            var logInfo = new Log();
            logInfo.setClassName(className)
                    .setMethodName(methodName)
                    .setPath(recordlog.value())
                    .setUserId("wdq")
                    .setTaskTime((endTime - startTime) * 1.0 / 1000)
                    .setParams(params)
                    .setCreateTime(String.valueOf(createTime));

            executor.submit(
                    () -> {
                        mongoTemplate.insert(logInfo);
                    }
            );


        }


    }
}